RPCGEN

Section: User Commands (1)
Updated: 11 March 1986
Index Return to Main Contents
 

NAME

rpcgen - an RPC protocol compiler  

SYNOPSIS

rpcgen -h [-o outfile] [inputfile]
rpcgen -c [-o outfile] [infile]
rpcgen infile
rpcgen [-s transport]* [-o outfile] [infile]
 

DESCRIPTION

rpcgen is a tool that generates C code to implement an RPC protocol. The input to rpcgen is a language with striking similarity to C known as RPCL (Remote Procedure Call Language). rpcgen operates in four modes. The first mode is used to convert RPCL definitions into C definitions for use as a header file. The second mode compiles the XDR routines required to serialize the protocol described by RPCL. The third mode compiles both, leaving the header file in a file named infile with a .h extension and the XDR routines in infile with a .c extension. The fourth mode is used to compile an RPC server skeleton, so that all you have to do is write local procedures that know nothing about RPC in order to implement an RPC server.

The input may contain C-style comments and preprocessor directives. Comments are ignored, while the directives are simply stuffed uninterpreted in the output header file.

You can customize some of your XDR routines by leaving those data types undefined. For every data type that is undefined, rpcgen will assume that there exists a routine with the name `xdr_' prepended to the name of the undefined type.  

OPTIONS

-c
Compile XDR routines.
-h
Compile C data-definitions (a header file)
-o outfile
Specify the name of the output file. If none is specified, standard output is used (-c, -h and -s modes only).
-s transport
Compile a server, using the the given transport. The supported transports are udp and tcp. This option may be invoked more than once so as to compile a server that serves multiple transports.
 

USAGE

 

RPCL Syntax Summary

This summary of RPCL syntax, which is used for rpcgen input, is intended more for aiding comprehension than as an exact statement of the language.  

Primitive Data Types

[ unsigned ] char
[ unsigned ] short
[ unsigned ] int
[ unsigned ] long
unsigned
float
double
void
bool
Except for the added boolean data-type bool, RPCL is identical to C. rpcgen converts bool declarations to int declarations in the output header file (literally it is converted to a bool_t, which has been #define'd to be an int). Also, void declarations may appear only inside of union and program definitions. For those averse to typing the prefix unsigned, the abbreviations u_char, u_short, u_int and u_long are available.  

Declarations

RPCL allows only three kinds of declarations:

declaration:

simple-declaration
pointer-declaration
vector-declaration

simple-declaration:

type-name object-ident

pointer-declaration:

type-name *object-ident

vector-declaration:

type-name object-ident[size]

(size can be either an integer or a symbolic constant)

RPCL declarations contain both limitations and extensions with respect to C. The limitations are that you cannot declare multidimensional arrays or pointers-to-pointers in-line (You can still declare them though, using typedef). There are two extensions:

Opaque data is declared as a vector as follows:

opaque object-ident [ size ]

In the protocol, this results in an object of size bytes. Note that this is not the same as a declaration of size characters, since XDR characters are 32-bits. Opaque declarations are compiled in the output header file into character array declarations of size bytes.

Strings are special and are declared as a vector declaration:

string object-ident [ max-size ]

If max-size is unspecified, then there is essentially no limit to the maximum length of the string. String declarations get compiled into the following:

char *object-ident
 

Type Definitions

The only way to generate an XDR routine is to define a type. For every type zetype you define, there is a corresponding XDR routine named xdr_zetype.

There are six ways to define a type:

type-definition:

typedef
enumeration-def
structure-def
variable-length-array-def
discriminated-union-def
program-def

The first three are very similar to their C namesakes. C does not have a formal type mechanism to define variable-length arrays and XDR unions are quite different from their C counterparts. Program definitions are not really type definitions, but they are useful nonetheless.

You may not nest XDR definitions. For example, the following will cause rpcgen to choke:

struct dontdoit {
        struct ididit {
                int oops;
        } sorry;
        enum ididitagain { OOPS, WHOOPS } iapologize;
};
 

Typedefs

An XDR typedef looks as follows:

typedef:

typedef declaration ;
The object-ident part of declaration is the name of the new type, whereas the type-name part is the name of the type from which it is derived.

 

Enumeration Types

The syntax is:

enumeration-def:

enum enum-ident {
enum-list
};

enum-list:

enum-symbol-ident [ = assignment ]
enum-symbol-ident [ = assignment ] , enum-list

(assignment may be either an integer or a symbolic constant)

If there is no explicit assignment, then the implicit assignment is the value of the previous enumeration plus 1. If not explicitly assigned, the first enumeration receives the value 0.  

Structures

structure-def:
struct struct-ident {
declaration-list
};

declaration-list:

declaration ;
declaration ; declaration-list

 

Variable-Length Arrays

variable-length-array-def:
array array-ident {
unsigned length-identifer ;
vector-declaration ;
};

A variable length array definition looks much like a structure definition. Here's an example:

array mp_int {
        unsigned len;
        short val[MAX_MP_LENGTH];
};
This is compiled into:
struct mp_int {
        unsigned len;
        short *val;
};
typedef struct mp_int mp_int;
 

Disriminated Unions

discriminated-union-def:
union union-ident switch ( discriminant-declaration ) {
case-list
[ default : declaration ; ]
};

case-list:

case case-ident : declaration ;
case case-ident : declaration ; case-list

discriminant-declaration:

declaration

The union definition looks like a cross between a C-union and a C-switch. An example:

union net_object switch (net_kind kind) {
case MACHINE:
        struct sockaddr_in sin;
case USER:
        int uid;
default:
        string whatisit;
};
Compiles into:
struct net_object {
        net_kind kind;
        union {
                struct sockaddr_in sin;
                int uid;
                char *whatisit;
        } net_object;
};
typedef struct net_object net_object;
Note that the name of the union component of the output struct is the same as the name of the type itself.  

Program Definitions

program-def:
program program-ident {
version-list
} = program-number ;

version-list:

version
version version-list
version:
version version-ident {
procedure-list
} = version-number ;
procedure-list:
procedure-declaration
procedure-declaration procedure-list
procedure-declaration:
type-name procedure-ident ( type-name ) = procedure-number ;

Program definitions look like nothing you've ever seen before, so we turn to an example to explain them. Suppose you wanted to create server that could get or set the date. It's declaration might look like this:

program DATE_PROG {
        version DATE_VERS {
                date DATE_GET(timezone) = 1;
                void DATE_SET(date) = 2;        /* Greenwich mean time */
        } = 1;
} = 100;
In the header file, this compiles into the following:
#define DATE_PROG 100
#define DATE_VERS 1
#define DATE_GET 1
#define DATE_SET 2
These define's are intended for use by the client program to reference the remote procedures.

If you are using rpcgen to compile your server, then there are some important things for you to know. The server interfaces to your local procedures by expecting a C function with the same name as that in the program definition, but in all lower-case letters and followed by the version number. Here is the local procedure that implements DATE_GET:

date *  /* always returns a pointer to the results */
date_get_1(tz)  
        timezone *tz;   /* always takes a a pointer to the arguments */
{
        static date d;  /* must be static! */
        
        /* 
         * figure out the date
         * and store it in d
         */
        return(&d);     
}
The name of the routine is the same as the #define'd name, but in all lower case letters and followed by the version number. XDR will recursively free the argument after getting the results from your local procedure, so you should copy from the argument any data that you will need between calls. However, XDR neither allocates nor frees your results. You must take care of their storage yourself.

 

Make Inference Rules For Compiling XDR Headers

It is possible to set up suffix transformation rules in make(1) for compiling XDR routines and header files. The convention is that RPCL protocol files have the extension .x. The make rules to do this are:

        .SUFFIXES: .x
        .x.c: 
                rpcgen -c $< -o $@

        .x.h:
                rpcgen -h $< -o $@
 

SEE ALSO

Remote Procedure Call: Programming Guide and External Data Representation: Protocol Specification in Networking on the Sun Workstation  

BUGS

Name clashes can occur when using program definitions, since the apparent scoping does not really apply. Most of these can be avoided by giving unique names for programs, versions, procedures and types.


 

Index

NAME
SYNOPSIS
DESCRIPTION
OPTIONS
USAGE
RPCL Syntax Summary
Primitive Data Types
Declarations
Type Definitions
Typedefs
Enumeration Types
Structures
Variable-Length Arrays
Disriminated Unions
Program Definitions
Make Inference Rules For Compiling XDR Headers
SEE ALSO
BUGS

This document was created by man2html, using the manual pages.
Time: 22:49:32 GMT, December 11, 2024